1 00:00:00,994 --> 00:00:16,401 [MUSIC PLAYING] 2 00:00:16,401 --> 00:00:19,520 PROFESSOR: Well, let's see. 3 00:00:19,520 --> 00:00:21,800 What we did so far was a lot of fun, was 4 00:00:21,800 --> 00:00:23,050 it useful for anything? 5 00:00:26,330 --> 00:00:29,380 I suppose the answer is going to be yes. 6 00:00:29,380 --> 00:00:33,930 If these metacircular interpreters are a valuable 7 00:00:33,930 --> 00:00:35,180 thing to play with. 8 00:00:38,050 --> 00:00:41,300 Well, there have been times I spend 50% of my time, over a 9 00:00:41,300 --> 00:00:46,590 year, trying various design alternatives by experimenting 10 00:00:46,590 --> 00:00:49,600 with them with metacircular interpreters-- 11 00:00:49,600 --> 00:00:52,570 metacircular interpreters like the sort you just saw. 12 00:00:52,570 --> 00:00:55,910 Metacircular is because they are defined in terms of 13 00:00:55,910 --> 00:00:58,830 themselves in such a way that the language they interpret 14 00:00:58,830 --> 00:01:01,270 contains itself. 15 00:01:01,270 --> 00:01:04,080 Such interpreters are a convenient medium for 16 00:01:04,080 --> 00:01:06,800 exploring language issues. 17 00:01:06,800 --> 00:01:11,010 If you want to try adding a new feature, it's sort of a 18 00:01:11,010 --> 00:01:15,490 snap, it's easy, you just do it and see what happens. 19 00:01:15,490 --> 00:01:17,710 You play with that language for a while you say, gee, I'm 20 00:01:17,710 --> 00:01:21,090 didn't like that, you throw it away. 21 00:01:21,090 --> 00:01:24,640 Or you might want to see what the difference is if you'd 22 00:01:24,640 --> 00:01:30,080 make a slight difference in the binding strategy, or some 23 00:01:30,080 --> 00:01:33,720 more complicated things that might occur. 24 00:01:33,720 --> 00:01:36,810 In fact, these metacircular interpreters are an excellent 25 00:01:36,810 --> 00:01:44,030 medium for people exchanging ideas about language design, 26 00:01:44,030 --> 00:01:46,960 because they're pretty easy to understand, and they're short, 27 00:01:46,960 --> 00:01:49,690 and compact, and simple. 28 00:01:49,690 --> 00:01:54,360 If I have some idea that I want somebody to criticize 29 00:01:54,360 --> 00:02:00,770 like say, Dan Friedman at Indiana, I'd write a little 30 00:02:00,770 --> 00:02:04,260 metacircular interpreter and send him some network mail 31 00:02:04,260 --> 00:02:05,450 with this interpreter in it. 32 00:02:05,450 --> 00:02:07,900 He could whip it up on his machine and play with it and 33 00:02:07,900 --> 00:02:11,940 say, that's no good. 34 00:02:11,940 --> 00:02:13,706 And then send it back to me and say, well, why don't you 35 00:02:13,706 --> 00:02:16,880 try this one, it's a little better. 36 00:02:16,880 --> 00:02:20,160 So I want to show you some of that technology. 37 00:02:20,160 --> 00:02:24,750 See, because, really, it's the essential, simple technology 38 00:02:24,750 --> 00:02:27,760 for getting started in designing your own languages 39 00:02:27,760 --> 00:02:30,790 for particular purposes. 40 00:02:30,790 --> 00:02:34,210 Let's start by adding a very simple feature to a Lisp. 41 00:02:40,640 --> 00:02:42,800 Now, one thing I want to tell you about is 42 00:02:42,800 --> 00:02:44,370 features, before I start. 43 00:02:49,560 --> 00:02:53,100 There are many languages that have made a mess of themselves 44 00:02:53,100 --> 00:02:56,620 by adding huge numbers of features. 45 00:02:56,620 --> 00:03:00,620 Computer scientists have a joke about bugs that transform 46 00:03:00,620 --> 00:03:02,520 it to features all the time. 47 00:03:05,030 --> 00:03:10,120 But I like to think of it is that many systems suffer from 48 00:03:10,120 --> 00:03:12,820 what's called creeping featurism. 49 00:03:12,820 --> 00:03:17,740 Which is that George has a pet feature he'd like in the 50 00:03:17,740 --> 00:03:20,170 system, so he adds it. 51 00:03:20,170 --> 00:03:23,480 And then Harry says, gee, this system is no longer what 52 00:03:23,480 --> 00:03:26,640 exactly I like, so I'm going to add my favorite feature. 53 00:03:26,640 --> 00:03:30,710 And then Jim adds his favorite feature. 54 00:03:30,710 --> 00:03:35,280 And, after a while, the thing has a manual 500 pages long 55 00:03:35,280 --> 00:03:37,790 that no one can understand. 56 00:03:37,790 --> 00:03:40,780 And sometimes it's the same person who writes all of these 57 00:03:40,780 --> 00:03:44,830 features and produces this terribly complicated thing. 58 00:03:44,830 --> 00:03:48,250 In some cases, like editors, it's sort of reasonable to 59 00:03:48,250 --> 00:03:51,940 have lots of features, because there are a lot of things you 60 00:03:51,940 --> 00:03:55,730 want to be able to do and many of them arbitrary. 61 00:03:55,730 --> 00:04:00,440 But in computer languages, I think it's a disaster to have 62 00:04:00,440 --> 00:04:01,690 too much stuff in them. 63 00:04:04,110 --> 00:04:06,860 The other alternative you get into is something called 64 00:04:06,860 --> 00:04:12,300 feeping creaturism, which is where you have a box which has 65 00:04:12,300 --> 00:04:17,370 a display, a fancy display, and a mouse, and there is all 66 00:04:17,370 --> 00:04:21,010 sorts of complexity associated with all this fancy IO. 67 00:04:21,010 --> 00:04:24,430 And your computer language becomes a dismal, little, tiny 68 00:04:24,430 --> 00:04:26,430 thing that barely works because of all the swapping, 69 00:04:26,430 --> 00:04:30,080 and disk twitching, and so on, caused by your Windows system. 70 00:04:30,080 --> 00:04:32,650 And every time you go near the computer, the mouse process 71 00:04:32,650 --> 00:04:35,910 wakes up and says, gee do you have something for me to do, 72 00:04:35,910 --> 00:04:37,440 and then it goes back to sleep. 73 00:04:37,440 --> 00:04:40,210 And if you accidentally push mouse with you elbow, a big 74 00:04:40,210 --> 00:04:41,600 puff of smoke comes out of your computer 75 00:04:41,600 --> 00:04:42,940 and things like that. 76 00:04:42,940 --> 00:04:46,030 So two ways to disastrously destroy a 77 00:04:46,030 --> 00:04:47,500 system by adding features. 78 00:04:47,500 --> 00:04:49,730 But try right now to add a little, simple feature. 79 00:04:52,300 --> 00:04:54,350 This actually is a good one, and in fact, 80 00:04:54,350 --> 00:04:57,250 real Lisps have it. 81 00:04:57,250 --> 00:05:03,420 As you've seen, there are procedures like plus and times 82 00:05:03,420 --> 00:05:05,430 that take any number of arguments. 83 00:05:05,430 --> 00:05:09,440 So we can write things like the sum of the product of a 84 00:05:09,440 --> 00:05:17,540 and x and x, and the product of b and x and c. 85 00:05:17,540 --> 00:05:21,210 As you can see here, addition takes three arguments or two 86 00:05:21,210 --> 00:05:24,230 arguments, multiplication takes two arguments or three 87 00:05:24,230 --> 00:05:27,290 arguments, taking numbers of arguments all of which are to 88 00:05:27,290 --> 00:05:30,000 be treated in the same way. 89 00:05:30,000 --> 00:05:32,300 This is a valuable thing, 90 00:05:32,300 --> 00:05:34,960 indefinite numbers of arguments. 91 00:05:34,960 --> 00:05:40,460 Yet the particular Lisp system that I showed you is one where 92 00:05:40,460 --> 00:05:43,600 the numbers of arguments is fixed, because I had to match 93 00:05:43,600 --> 00:05:45,910 the arguments against the formal parameters in the 94 00:05:45,910 --> 00:05:47,850 binder, where there's a pairup. 95 00:05:50,810 --> 00:05:53,460 Well, I'd like to be able to define new procedures like 96 00:05:53,460 --> 00:05:58,590 this that can have any number of arguments. 97 00:05:58,590 --> 00:06:01,150 Well there's several parts to this problem. 98 00:06:01,150 --> 00:06:03,870 The first part is coming up with the syntactic 99 00:06:03,870 --> 00:06:10,620 specification, some way of notating the additional 100 00:06:10,620 --> 00:06:15,480 arguments, of which you don't know how many there are. 101 00:06:15,480 --> 00:06:17,980 And then there's the other thing, which is once we've 102 00:06:17,980 --> 00:06:21,940 notated it, how are we going to interpret that notation so 103 00:06:21,940 --> 00:06:26,980 as to do the right thing, whatever the right thing is? 104 00:06:26,980 --> 00:06:29,230 So let's consider an example of a sort of thing we might 105 00:06:29,230 --> 00:06:30,480 want to be able to do. 106 00:06:33,070 --> 00:06:36,380 So an example might be, that I might want to be able to 107 00:06:36,380 --> 00:06:40,490 define a procedure which is a procedure of one required 108 00:06:40,490 --> 00:06:45,820 argument x and a bunch of arguments, I don't know how 109 00:06:45,820 --> 00:06:49,090 many there are, called y. 110 00:06:49,090 --> 00:07:00,725 So x is required, and there are many y's, many argument-- 111 00:07:04,710 --> 00:07:05,990 y will be the list of them. 112 00:07:14,480 --> 00:07:17,370 Now, with such a thing, we might be able to say something 113 00:07:17,370 --> 00:07:20,720 like, map-- 114 00:07:20,720 --> 00:07:22,590 I'm going to do something to every one-- 115 00:07:22,590 --> 00:07:30,055 of that procedure of one argument u, which multiplies x 116 00:07:30,055 --> 00:07:36,890 by u, and we'll apply that to y. 117 00:07:36,890 --> 00:07:41,020 I've used a dot here to indicate that the thing after 118 00:07:41,020 --> 00:07:46,300 this is a list of all the rest of the arguments. 119 00:07:46,300 --> 00:07:47,745 I'm making a syntactic specification. 120 00:07:53,320 --> 00:07:56,870 Now, what this depends upon, the reason why this is sort of 121 00:07:56,870 --> 00:08:01,440 a reasonable thing to do, is because this happens to be a 122 00:08:01,440 --> 00:08:04,640 syntax that's used in the Lisp reader for 123 00:08:04,640 --> 00:08:08,631 representing conses. 124 00:08:08,631 --> 00:08:11,080 We've never introduced that before. 125 00:08:11,080 --> 00:08:13,680 You may have seen when playing with the system that if you 126 00:08:13,680 --> 00:08:16,740 cons two things together, you get the first, space, dot, the 127 00:08:16,740 --> 00:08:19,800 second, space-- 128 00:08:19,800 --> 00:08:23,880 the first, space, dot, space, the second with parentheses 129 00:08:23,880 --> 00:08:26,980 around the whole thing. 130 00:08:26,980 --> 00:08:36,350 So that, for example, this x dot y corresponds to a pair, 131 00:08:36,350 --> 00:08:41,870 which has got an x in it and a y in it. 132 00:08:41,870 --> 00:08:45,520 The other notations that you've seen so far are things 133 00:08:45,520 --> 00:08:55,720 like a procedure of arguments x and y and z which do things, 134 00:08:55,720 --> 00:08:57,590 and that looks like-- 135 00:09:02,000 --> 00:09:04,910 Just looking at the bound variable list, it looks like 136 00:09:04,910 --> 00:09:18,280 this, x, y, z, and the empty thing. 137 00:09:18,280 --> 00:09:22,590 If I have a list of arguments I wish to match this against, 138 00:09:22,590 --> 00:09:26,110 supposing, I have a list of arguments one, two, three, I 139 00:09:26,110 --> 00:09:36,300 want to match these against. So I might have here a list of 140 00:09:36,300 --> 00:09:46,380 three things, one, two, three. 141 00:09:48,990 --> 00:09:54,220 And I want to match x, y, z against one, two, three. 142 00:09:54,220 --> 00:09:56,830 Well, it's clear that the one matches the x, because I can 143 00:09:56,830 --> 00:10:00,130 just sort of follow the structure, and the two matches 144 00:10:00,130 --> 00:10:05,480 the y, and the three matches the z. 145 00:10:05,480 --> 00:10:09,560 But now, supposing I were to compare this x dot y-- 146 00:10:09,560 --> 00:10:12,460 this is x dot y-- 147 00:10:12,460 --> 00:10:16,010 supposing I compare that with a list of three arguments, 148 00:10:16,010 --> 00:10:18,510 one, two, three. 149 00:10:18,510 --> 00:10:20,000 Let's look at that again. 150 00:10:28,000 --> 00:10:30,930 One, two, three-- 151 00:10:30,930 --> 00:10:34,970 Well, I can walk along here and say, oh yes, x matches the 152 00:10:34,970 --> 00:10:43,740 one, the y matches the list, which is two and three. 153 00:10:43,740 --> 00:10:47,150 So the notation I'm choosing here is one that's very 154 00:10:47,150 --> 00:10:50,160 natural for Lisp system. 155 00:10:52,660 --> 00:10:54,790 But I'm going to choose this as a notation for representing 156 00:10:54,790 --> 00:10:56,040 a bunch of arguments. 157 00:10:58,290 --> 00:11:00,770 Now, there's an alternative possibility. 158 00:11:00,770 --> 00:11:03,560 If I don't want to take one special out, or two special 159 00:11:03,560 --> 00:11:07,300 ones out or something like that, if I don't want to do 160 00:11:07,300 --> 00:11:11,420 that, if I want to talk about just the list of all the 161 00:11:11,420 --> 00:11:16,950 arguments like in addition, well then the argument list 162 00:11:16,950 --> 00:11:20,370 I'm going to choose to be that procedure of all the arguments 163 00:11:20,370 --> 00:11:25,140 x which does something with x. 164 00:11:25,140 --> 00:11:29,190 And which, for example, if I take the procedure, which 165 00:11:29,190 --> 00:11:35,040 takes all the arguments x and returned the list of them, 166 00:11:35,040 --> 00:11:45,850 that's list. That's the procedure list. 167 00:11:45,850 --> 00:11:46,840 How does this work? 168 00:11:46,840 --> 00:11:49,610 Well, indeed what I had as the bound variable list in this 169 00:11:49,610 --> 00:11:52,450 case, whatever it is, is being matched 170 00:11:52,450 --> 00:11:55,140 against a list of arguments. 171 00:11:55,140 --> 00:11:57,145 This symbol now is all of the arguments. 172 00:12:01,490 --> 00:12:03,830 And so this is the choice I'm making for a particular 173 00:12:03,830 --> 00:12:08,060 syntactic specification, for the description of procedures 174 00:12:08,060 --> 00:12:10,285 which take indefinite numbers of arguments. 175 00:12:13,190 --> 00:12:18,420 There are two cases of it, this one and this one. 176 00:12:18,420 --> 00:12:21,330 When you make syntactic specifications, it's important 177 00:12:21,330 --> 00:12:26,410 that it's unambiguous, that neither of these can be 178 00:12:26,410 --> 00:12:31,100 confused with a representation we already have, this one. 179 00:12:33,610 --> 00:12:38,350 I can always tell whether I have a fixed number of 180 00:12:38,350 --> 00:12:41,180 explicitly named arguments made by these formal 181 00:12:41,180 --> 00:12:45,470 parameters, or a fixed number of named formal parameters 182 00:12:45,470 --> 00:12:49,240 followed by a thing which picks up all the rest of them, 183 00:12:49,240 --> 00:12:54,620 or a list of all the arguments which will be matched against 184 00:12:54,620 --> 00:12:57,170 this particular formal parameter called x, because 185 00:12:57,170 --> 00:12:58,465 these are syntactically distinguishable. 186 00:13:02,250 --> 00:13:05,960 Many languages make terrible errors in that form where 187 00:13:05,960 --> 00:13:08,340 whole segments of interpretation are cut off, 188 00:13:08,340 --> 00:13:14,560 because there are syntactic ambiguities in the language. 189 00:13:14,560 --> 00:13:16,330 They are the traditional problems with ALGOL like 190 00:13:16,330 --> 00:13:22,810 languages having to do with the nesting of ifs in the 191 00:13:22,810 --> 00:13:25,060 predicate part. 192 00:13:25,060 --> 00:13:30,510 In any case, now, so I've told you about the syntax, now, 193 00:13:30,510 --> 00:13:35,250 what are we going to do about the semantics of this? 194 00:13:35,250 --> 00:13:36,590 How do we interpret it? 195 00:13:36,590 --> 00:13:38,440 Well this is just super easy. 196 00:13:38,440 --> 00:13:39,900 I'm going to modify the metacircular 197 00:13:39,900 --> 00:13:43,396 interpreter to do it. 198 00:13:43,396 --> 00:13:46,020 And that's a one liner. 199 00:13:46,020 --> 00:13:47,590 There it is. 200 00:13:47,590 --> 00:13:49,560 I'm changing the way you pair things up. 201 00:13:56,390 --> 00:14:06,070 Here's the procedure that pairs the variables, the 202 00:14:06,070 --> 00:14:12,090 formal parameters, with the arguments that were passed 203 00:14:12,090 --> 00:14:16,080 from the last description of the metacircular interpreter. 204 00:14:18,960 --> 00:14:20,840 And here's some things that are the same 205 00:14:20,840 --> 00:14:22,670 as they were before. 206 00:14:22,670 --> 00:14:25,880 In other words, if the list of variables is empty, then if 207 00:14:25,880 --> 00:14:31,050 the list of values is empty, then I have an empty list. 208 00:14:31,050 --> 00:14:36,890 Otherwise, I have too many arguments, that is, if I have 209 00:14:36,890 --> 00:14:41,580 empty variables but not empty values. 210 00:14:41,580 --> 00:14:47,713 If I have empty values, but the variables are not empty, I 211 00:14:47,713 --> 00:14:50,090 have too few arguments. 212 00:14:50,090 --> 00:14:51,340 The variables are a symbol-- 213 00:14:55,620 --> 00:14:58,130 interesting case-- 214 00:14:58,130 --> 00:15:04,040 then, what I should do is say, oh yes, this is the special 215 00:15:04,040 --> 00:15:06,255 case that I have a symbolic tail. 216 00:15:09,010 --> 00:15:14,900 I have here a thing just like we looked over here. 217 00:15:14,900 --> 00:15:18,630 This is a tail which is a symbol, y. 218 00:15:18,630 --> 00:15:20,730 It's not a nil. 219 00:15:20,730 --> 00:15:24,290 It's not the empty list. Here's a symbolic tail that is 220 00:15:24,290 --> 00:15:25,600 just the very beginning of the tail. 221 00:15:25,600 --> 00:15:27,790 There is nothing else. 222 00:15:27,790 --> 00:15:36,540 In that case, I wish to match that variable with all the 223 00:15:36,540 --> 00:15:44,500 values and add that to the pairing that I'm making. 224 00:15:44,500 --> 00:15:47,660 Otherwise, I go through the normal arrangement of making 225 00:15:47,660 --> 00:15:48,910 up the whole pairing. 226 00:15:52,020 --> 00:15:54,510 I suppose that's very simple. 227 00:15:54,510 --> 00:15:57,080 And that's all there is to it. 228 00:15:57,080 --> 00:15:58,330 And now I'll answer some questions. 229 00:16:02,620 --> 00:16:04,220 The first one-- 230 00:16:04,220 --> 00:16:06,600 Are there any questions? 231 00:16:06,600 --> 00:16:06,950 Yes? 232 00:16:06,950 --> 00:16:10,450 AUDIENCE: Could you explain that third form? 233 00:16:10,450 --> 00:16:12,590 PROFESSOR: This one? 234 00:16:12,590 --> 00:16:15,280 Well, maybe we should look at the thing as a 235 00:16:15,280 --> 00:16:18,570 piece of list structure. 236 00:16:18,570 --> 00:16:22,400 This is a procedure which contains a lambda. 237 00:16:25,970 --> 00:16:27,110 I'm just looking at the list structure 238 00:16:27,110 --> 00:16:31,090 which represents this. 239 00:16:31,090 --> 00:16:32,730 Here's x. 240 00:16:32,730 --> 00:16:33,980 These are our symbols. 241 00:16:37,410 --> 00:16:39,580 And then the body is nothing but x. 242 00:16:44,840 --> 00:16:48,040 If I were looking for the bound variable list part of 243 00:16:48,040 --> 00:16:52,400 this procedure, I would go looking at the CADR, and I'd 244 00:16:52,400 --> 00:16:54,010 find a symbol. 245 00:16:54,010 --> 00:16:56,750 So the, naturally, which is this pairup thing I just 246 00:16:56,750 --> 00:17:01,570 showed you, is going to be matching a symbolic object 247 00:17:01,570 --> 00:17:05,760 against a list of arguments that were passed. 248 00:17:05,760 --> 00:17:09,559 And it will bind that symbol to the list of arguments. 249 00:17:13,910 --> 00:17:18,560 In this case, if I'm looking for it, the match will be 250 00:17:18,560 --> 00:17:20,920 against this in the bound variable list position. 251 00:17:24,140 --> 00:17:27,020 Now, if what this does is it gets a list of arguments and 252 00:17:27,020 --> 00:17:31,450 returns it, that's list. That's what the procedure is. 253 00:17:34,510 --> 00:17:36,140 Oh well, thank you. 254 00:17:36,140 --> 00:17:37,830 Let's take a break. 255 00:17:37,830 --> 00:18:20,358 [MUSIC PLAYING] 256 00:18:20,358 --> 00:18:23,260 PROFESSOR: Well let's see. 257 00:18:23,260 --> 00:18:24,760 Now, I'm going to tell you about a rather more 258 00:18:24,760 --> 00:18:32,440 substantial variation, one that's a famous variation that 259 00:18:32,440 --> 00:18:38,250 many early Lisps had. 260 00:18:38,250 --> 00:18:41,770 It's called dynamic binding of variables. 261 00:18:41,770 --> 00:18:44,680 And we'll investigate a little bit about that right now. 262 00:18:47,620 --> 00:18:49,710 I'm going to first introduce this by showing you the sort 263 00:18:49,710 --> 00:18:53,740 of thing that would make someone want this idea. 264 00:18:53,740 --> 00:18:56,680 I'm not going to tell what it is yet, I'm going to show you 265 00:18:56,680 --> 00:18:58,640 why you might want it. 266 00:18:58,640 --> 00:19:02,100 Suppose, for example, we looked at the sum procedure 267 00:19:02,100 --> 00:19:08,140 again for summing up a bunch of things. 268 00:19:08,140 --> 00:19:15,860 To be that procedure, of a term, lower bound, method of 269 00:19:15,860 --> 00:19:25,560 computing the next index, and upper bound, such that, if a 270 00:19:25,560 --> 00:19:34,020 is greater than b then the result is 0, otherwise, it's 271 00:19:34,020 --> 00:19:40,680 the sum, of the term, procedure, applied to a and 272 00:19:40,680 --> 00:19:51,925 the result of adding up, terms, with the next a being 273 00:19:51,925 --> 00:20:06,970 the a, the next procedure passed along, and the upper 274 00:20:06,970 --> 00:20:08,220 bound being passed along. 275 00:20:14,510 --> 00:20:15,760 Blink, blink, blink-- 276 00:20:18,900 --> 00:20:23,350 Now, when I use this sum procedure, I can use it, for 277 00:20:23,350 --> 00:20:25,450 example, like this. 278 00:20:25,450 --> 00:20:38,680 We can define the sum of the powers to be, for example, sum 279 00:20:38,680 --> 00:20:43,240 of a bunch of powers x to the n, to be that procedure 280 00:20:43,240 --> 00:20:45,970 of a, b, and n-- 281 00:20:45,970 --> 00:20:48,150 lower bound, the upper bound, and n-- 282 00:20:48,150 --> 00:20:54,530 which is sum, of lambda of x, the procedure of one argument 283 00:20:54,530 --> 00:21:05,720 x, which exponentiates x to the n, with the a, the 284 00:21:05,720 --> 00:21:11,440 incrementer, and b, being passed along. 285 00:21:11,440 --> 00:21:16,340 So we're adding up x to n, given an x. 286 00:21:16,340 --> 00:21:19,740 x takes on values from a to b, incrementing by one. 287 00:21:22,940 --> 00:21:24,300 I can also write the-- 288 00:21:27,670 --> 00:21:29,780 That's right. 289 00:21:29,780 --> 00:21:31,910 Product, excuse me. 290 00:21:31,910 --> 00:21:33,220 The product of a bunch of powers. 291 00:21:38,080 --> 00:21:40,020 It's a strange name. 292 00:21:40,020 --> 00:21:41,960 I'm going to leave it there. 293 00:21:41,960 --> 00:21:43,210 Weird-- 294 00:21:45,760 --> 00:21:50,890 I write up what I have. I'm sure that's right. 295 00:21:50,890 --> 00:21:53,720 And if I want the product of a bunch of powers-- 296 00:21:58,630 --> 00:22:03,400 That was 12 brain cells, that double-take. 297 00:22:03,400 --> 00:22:06,890 I can for example use the procedure which is like sum, 298 00:22:06,890 --> 00:22:10,080 which is for making products, but it's similar to that, that 299 00:22:10,080 --> 00:22:11,450 you've seen before. 300 00:22:11,450 --> 00:22:16,725 There's a procedure of three arguments again. 301 00:22:16,725 --> 00:22:24,080 Which is the product of terms that are constructed, or 302 00:22:24,080 --> 00:22:26,480 factors in this case, constructed from 303 00:22:26,480 --> 00:22:35,970 exponentiating x to the n, where I start with a, I 304 00:22:35,970 --> 00:22:37,850 increment, and I go to b. 305 00:22:41,530 --> 00:22:48,690 Now, there's some sort of thing here that should disturb 306 00:22:48,690 --> 00:22:50,750 you immediately. 307 00:22:50,750 --> 00:22:53,180 These look the same. 308 00:22:53,180 --> 00:22:56,590 Why am I writing this code so many times? 309 00:22:56,590 --> 00:23:01,270 Here I am, in the same boat I've been in before. 310 00:23:01,270 --> 00:23:03,810 Wouldn't it be nice to make an abstraction here? 311 00:23:03,810 --> 00:23:05,980 What's an example of a good abstraction to make? 312 00:23:05,980 --> 00:23:08,470 Well, I see some codes that's identical. 313 00:23:08,470 --> 00:23:11,080 Here's one, and here's another. 314 00:23:14,450 --> 00:23:17,090 And so maybe I should be able to pull that out. 315 00:23:17,090 --> 00:23:21,580 I should be able to say, oh yes, the sum of the powers 316 00:23:21,580 --> 00:23:23,350 could be written in terms of something called 317 00:23:23,350 --> 00:23:25,710 the nth power procedure. 318 00:23:25,710 --> 00:23:28,690 Imagine somebody wanted to write a slightly different 319 00:23:28,690 --> 00:23:30,030 procedure that looks like this. 320 00:23:37,630 --> 00:23:49,300 The sum powers to be a procedure of a, b, and n, as 321 00:23:49,300 --> 00:23:53,556 the result of summing up the nth power. 322 00:23:53,556 --> 00:23:59,720 We're going to give a name to that idea, for starting at a, 323 00:23:59,720 --> 00:24:02,170 going by one, and ending at b. 324 00:24:06,000 --> 00:24:12,480 And similarly, I might want to write the product powers this 325 00:24:12,480 --> 00:24:16,270 way, abstracting out this idea. 326 00:24:16,270 --> 00:24:17,520 I might want this. 327 00:24:22,100 --> 00:24:35,350 Product powers, to be a procedure of a, b, and n, 328 00:24:35,350 --> 00:24:47,540 which is the product of the nth power operation on a with 329 00:24:47,540 --> 00:24:56,380 the incrementation and b being my arguments for the 330 00:24:56,380 --> 00:24:58,380 analogous-thing product. 331 00:24:58,380 --> 00:25:02,840 And I'd like to be able to define, I'd like to be able to 332 00:25:02,840 --> 00:25:04,680 define nth power-- 333 00:25:04,680 --> 00:25:05,930 I'll put it over here. 334 00:25:11,215 --> 00:25:12,990 I'll put it at the top. 335 00:25:25,410 --> 00:25:30,630 --to be, in fact, my procedure of one argument x which is the 336 00:25:30,630 --> 00:25:35,390 result of exponentiating x to the n. 337 00:25:35,390 --> 00:25:38,640 But I have a problem. 338 00:25:38,640 --> 00:25:44,160 My environment model, that is my means of interpretation for 339 00:25:44,160 --> 00:25:47,010 the language that we've defined so far, does not give 340 00:25:47,010 --> 00:25:48,810 me a meaning for this n. 341 00:25:52,520 --> 00:26:06,410 Because, as you know, this n is free in this procedure. 342 00:26:06,410 --> 00:26:09,600 The environment model tells us that the meaning of a free 343 00:26:09,600 --> 00:26:13,760 variable is determined in the environment in which this 344 00:26:13,760 --> 00:26:16,640 procedure is defined. 345 00:26:16,640 --> 00:26:18,120 In a way I have written it, assuming these things are 346 00:26:18,120 --> 00:26:22,830 defined on the blackboard as is, this is defined in the 347 00:26:22,830 --> 00:26:25,850 global environment, where there is no end. 348 00:26:25,850 --> 00:26:28,720 Therefore, n is unbound variable. 349 00:26:28,720 --> 00:26:33,390 But it's perfectly clear, to most of us, that we would like 350 00:26:33,390 --> 00:26:36,220 it to be this n and this n. 351 00:26:38,990 --> 00:26:42,840 On the other hand, it would be nice. 352 00:26:42,840 --> 00:26:45,290 Certainly we've got to be careful here of keeping this 353 00:26:45,290 --> 00:26:51,005 to be this, and this one over here, wherever it 354 00:26:51,005 --> 00:26:52,900 is to be this one. 355 00:26:57,390 --> 00:27:01,360 Well, the desire to make this work has led to 356 00:27:01,360 --> 00:27:04,040 a very famous bug. 357 00:27:04,040 --> 00:27:07,310 I'll tell you about the famous bug. 358 00:27:07,310 --> 00:27:10,660 Look at this slide. 359 00:27:10,660 --> 00:27:13,990 This is an idea called dynamic binding. 360 00:27:13,990 --> 00:27:17,980 Where, instead of the free variable being interpreted in 361 00:27:17,980 --> 00:27:22,820 the environment of definition of a procedure, the free 362 00:27:22,820 --> 00:27:25,770 variable is interpreted as having its value in the 363 00:27:25,770 --> 00:27:29,125 environment of the caller of the procedure. 364 00:27:31,850 --> 00:27:36,680 So what you have is a system where you search up the chain 365 00:27:36,680 --> 00:27:41,990 of callers of a particular procedure, and, of course, in 366 00:27:41,990 --> 00:27:45,240 this case, since nth power is called from inside product 367 00:27:45,240 --> 00:27:46,010 whatever it is-- 368 00:27:46,010 --> 00:27:48,140 I had to write our own sum which is the analogous 369 00:27:48,140 --> 00:27:50,530 procedure-- 370 00:27:50,530 --> 00:27:55,300 and product is presumably called from product powers, as 371 00:27:55,300 --> 00:27:58,490 you see over here, then since product powers bind with 372 00:27:58,490 --> 00:28:03,220 variable n , then nth powers n would be derived 373 00:28:03,220 --> 00:28:04,470 through that chain. 374 00:28:08,140 --> 00:28:12,600 Similarly, this n, the nth power in n in this case, would 375 00:28:12,600 --> 00:28:15,800 come through nth power here being called from inside sum. 376 00:28:15,800 --> 00:28:19,730 You can see it being called from inside sum here. 377 00:28:19,730 --> 00:28:22,900 It's called term here. 378 00:28:22,900 --> 00:28:28,930 But sum was called from inside of sum powers, which bound n. 379 00:28:28,930 --> 00:28:35,245 Therefore, there would be an n available for that n to get 380 00:28:35,245 --> 00:28:36,495 it's value from. 381 00:28:39,430 --> 00:28:43,630 What we have below this white line plus over here, is what's 382 00:28:43,630 --> 00:28:46,540 called a dynamic binding view of the world. 383 00:28:46,540 --> 00:28:50,850 If that works, that's a dynamic binding view. 384 00:28:50,850 --> 00:28:55,310 Now, let's take a look, for example, at just what it takes 385 00:28:55,310 --> 00:28:55,990 to implement that. 386 00:28:55,990 --> 00:28:57,480 That's real easy. 387 00:28:57,480 --> 00:29:01,400 In fact, the very first Lisps that had any interpretations 388 00:29:01,400 --> 00:29:04,440 of the free variables at all, had dynamic binding 389 00:29:04,440 --> 00:29:06,490 interpretations for the free variables. 390 00:29:06,490 --> 00:29:09,570 APL has dynamic binding interpretation for the free 391 00:29:09,570 --> 00:29:15,220 variables, not lexical or static binding. 392 00:29:15,220 --> 00:29:18,790 So, of course, the change is in eval. 393 00:29:18,790 --> 00:29:22,780 And it's really in two places. 394 00:29:22,780 --> 00:29:27,760 First of all, one thing we see, is that things become a 395 00:29:27,760 --> 00:29:29,010 little simpler. 396 00:29:32,460 --> 00:29:34,930 If I don't have to have the environment be the environment 397 00:29:34,930 --> 00:29:38,490 of definition for procedure, the procedure need not capture 398 00:29:38,490 --> 00:29:42,030 the environment at the time it's defined. 399 00:29:42,030 --> 00:29:47,900 And so if we look here at this slide, we see that the clause 400 00:29:47,900 --> 00:29:51,890 for a lambda expression, which is the way a procedure is 401 00:29:51,890 --> 00:29:57,820 defined, does not make up a thing which has a type closure 402 00:29:57,820 --> 00:30:01,290 and a attached environment structure. 403 00:30:01,290 --> 00:30:02,540 It's just the expression itself. 404 00:30:02,540 --> 00:30:06,440 And we'll decompose that some other way somewhere else. 405 00:30:06,440 --> 00:30:12,210 The other thing we see is the applicator must be able to get 406 00:30:12,210 --> 00:30:14,290 the environment of the caller. 407 00:30:14,290 --> 00:30:19,560 The caller of a procedure is right here. 408 00:30:19,560 --> 00:30:22,810 If the expression we're evaluating is anpplication or 409 00:30:22,810 --> 00:30:25,680 a combination, then we're going to call a procedure 410 00:30:25,680 --> 00:30:26,980 which is the value of the operator. 411 00:30:29,840 --> 00:30:33,100 The environment of the caller is the environment we have 412 00:30:33,100 --> 00:30:35,890 right here, available now. 413 00:30:35,890 --> 00:30:38,570 So all I have to do is pass that environment to the 414 00:30:38,570 --> 00:30:41,490 applicator, to apply. 415 00:30:41,490 --> 00:30:44,680 And if we look at that here, the only change we have to 416 00:30:44,680 --> 00:30:49,720 make is that fellow takes that environment and uses that 417 00:30:49,720 --> 00:30:57,240 environment for the purpose of extending that environment 418 00:30:57,240 --> 00:31:00,100 when abiding the formal parameters of the procedure to 419 00:31:00,100 --> 00:31:04,560 the arguments that were passed, not an environment 420 00:31:04,560 --> 00:31:06,810 that was captured in the procedure. 421 00:31:06,810 --> 00:31:09,780 The reason why the first Lisps were implemented this way, is 422 00:31:09,780 --> 00:31:14,130 the sort of the obvious, accidental implementation. 423 00:31:14,130 --> 00:31:15,990 And, of course, as usual, people got used to 424 00:31:15,990 --> 00:31:17,250 it and liked it. 425 00:31:17,250 --> 00:31:18,730 And there were some people said, this is 426 00:31:18,730 --> 00:31:21,590 the way to do it. 427 00:31:21,590 --> 00:31:25,870 Unfortunately that causes some serious problems. The most 428 00:31:25,870 --> 00:31:31,240 important, serious problem in using dynamic binding is 429 00:31:31,240 --> 00:31:35,460 there's a modularity crisis that's involved it. 430 00:31:35,460 --> 00:31:38,370 If two people are working together on some big system, 431 00:31:38,370 --> 00:31:41,580 then an important thing to want is that the names used by 432 00:31:41,580 --> 00:31:44,580 each one don't interfere with the names of the other. 433 00:31:47,930 --> 00:31:51,060 It's important that when I invent some segment of code 434 00:31:51,060 --> 00:31:54,985 that no one can make my code stop working by using my names 435 00:31:54,985 --> 00:31:59,850 that I use internal to my code, internal to his code. 436 00:31:59,850 --> 00:32:03,140 However, dynamic binding violates that particular 437 00:32:03,140 --> 00:32:06,670 modularity constraint in a clear way. 438 00:32:06,670 --> 00:32:12,540 Consider, for example, what happens over here. 439 00:32:12,540 --> 00:32:17,590 Suppose it was the case that I decided to 440 00:32:17,590 --> 00:32:19,810 change the word next. 441 00:32:19,810 --> 00:32:25,870 Supposing somebody is writing sum, and somebody else is 442 00:32:25,870 --> 00:32:28,970 going to use sum. 443 00:32:28,970 --> 00:32:33,790 The writer of sum has a choice of what names he may use. 444 00:32:33,790 --> 00:32:36,760 Let's say, I'm that writer. 445 00:32:36,760 --> 00:32:39,300 Well, by gosh, just happens I didn't want to call this next. 446 00:32:39,300 --> 00:32:41,500 I called it n. 447 00:32:41,500 --> 00:32:48,140 So all places where you see next, I called it n. 448 00:32:48,140 --> 00:32:49,940 Whoops. 449 00:32:49,940 --> 00:32:51,700 I changed nothing about the specifications of this 450 00:32:51,700 --> 00:32:56,110 program, but this program stops working. 451 00:32:56,110 --> 00:32:59,730 Not only that, unfortunately, this one does too. 452 00:32:59,730 --> 00:33:02,260 Why do these programs stop working? 453 00:33:02,260 --> 00:33:04,480 Well, it's sort of clear. 454 00:33:04,480 --> 00:33:09,890 Instead of chasing out the value of the n that occurs in 455 00:33:09,890 --> 00:33:16,450 nth power over here or over here, through the environment 456 00:33:16,450 --> 00:33:19,940 of definition, where this one is always linked to this one, 457 00:33:19,940 --> 00:33:21,660 if it was through the environment of definition, 458 00:33:21,660 --> 00:33:24,370 because here is the definition. 459 00:33:24,370 --> 00:33:27,320 This lambda expression was executed in the environment 460 00:33:27,320 --> 00:33:30,700 where that n was defined. 461 00:33:30,700 --> 00:33:33,150 If instead of doing that, I have to chase through the call 462 00:33:33,150 --> 00:33:37,320 chain, then look what horrible thing happens. 463 00:33:37,320 --> 00:33:44,780 Well, this was called from inside sum as term, term a. 464 00:33:44,780 --> 00:33:47,350 I'm looking for a value of n. 465 00:33:47,350 --> 00:33:50,700 Instead of getting this one, I get that one. 466 00:33:50,700 --> 00:33:53,430 So by changing the insides of this program, this program 467 00:33:53,430 --> 00:33:54,680 stops working. 468 00:33:56,770 --> 00:33:58,770 So I no longer have a quantifier, 469 00:33:58,770 --> 00:34:00,020 as I described before. 470 00:34:02,700 --> 00:34:05,430 The lambda symbol is supposed to be a quantifier. 471 00:34:05,430 --> 00:34:09,650 A thing which has the property that the names that are bound 472 00:34:09,650 --> 00:34:14,739 by it are unimportant, that I can uniformly substitute any 473 00:34:14,739 --> 00:34:18,230 names for these throughout this thing, so long as they 474 00:34:18,230 --> 00:34:21,699 don't occur in here, the new names, and the meaning of this 475 00:34:21,699 --> 00:34:24,040 expression should remain unchanged. 476 00:34:24,040 --> 00:34:26,050 I've just changed the meaning of the expression by changing 477 00:34:26,050 --> 00:34:28,690 the one of the names. 478 00:34:28,690 --> 00:34:32,170 So lambda is no longer a well defined idea. 479 00:34:32,170 --> 00:34:34,550 It's a very serious problem. 480 00:34:34,550 --> 00:34:40,850 So for that reason, I and my buddies have given up this 481 00:34:40,850 --> 00:34:43,650 particular kind of abstraction, which I would 482 00:34:43,650 --> 00:34:48,090 like to have, in favor of a modularity principle. 483 00:34:48,090 --> 00:34:52,310 But this is the kind of experiment you can do if you 484 00:34:52,310 --> 00:34:54,530 want to play with these interpreters. 485 00:34:54,530 --> 00:34:58,270 You can try them out this way, that way, and the other way. 486 00:34:58,270 --> 00:35:00,070 You see what makes a nicer language. 487 00:35:02,680 --> 00:35:04,990 So that's a very important thing to be able to do. 488 00:35:04,990 --> 00:35:07,260 Now, I would like to give you a feeling for I think the 489 00:35:07,260 --> 00:35:10,880 right thing to do is here. 490 00:35:10,880 --> 00:35:14,190 How are you going to I get this kind of power in a 491 00:35:14,190 --> 00:35:16,280 lexical system? 492 00:35:16,280 --> 00:35:18,610 And the answer is, of course, what I really want is a 493 00:35:18,610 --> 00:35:21,790 something that makes up for me an exponentiator for a 494 00:35:21,790 --> 00:35:23,690 particular n. 495 00:35:23,690 --> 00:35:26,280 Given an n, it will make me an exponentiator. 496 00:35:26,280 --> 00:35:28,170 Oh, but that's easy too. 497 00:35:28,170 --> 00:35:30,570 In other words, I can write my program this way. 498 00:35:35,450 --> 00:35:40,720 I'm going to define a thing called PGEN, which is a 499 00:35:40,720 --> 00:35:45,240 procedure of n which produces for me an exponentiator. 500 00:35:50,240 --> 00:35:51,490 --x to the n. 501 00:35:56,900 --> 00:36:00,310 Given that I have that, then I can capture the abstraction I 502 00:36:00,310 --> 00:36:04,090 wanted even better, because now it's encapsulated in a way 503 00:36:04,090 --> 00:36:07,890 where I can't be destroyed by a change of names. 504 00:36:07,890 --> 00:36:20,200 I can define some powers to be a procedure again of a, b, and 505 00:36:20,200 --> 00:36:28,070 n which is the sum of the term function generated by using 506 00:36:28,070 --> 00:36:37,590 this generator, PGEN, n, with a, incrementer, and b. 507 00:36:42,490 --> 00:36:57,100 And I can define the product of powers to be a procedure of 508 00:36:57,100 --> 00:37:09,010 a, b, and n which is the product PGEN, n, with a, 509 00:37:09,010 --> 00:37:11,150 increment, and b. 510 00:37:11,150 --> 00:37:14,340 Now, of course, this is a very simple example where this 511 00:37:14,340 --> 00:37:17,280 object that I'm trying to abstract over is small. 512 00:37:17,280 --> 00:37:20,100 But it could be a 100 lines of code. 513 00:37:20,100 --> 00:37:22,350 And so, the purpose of this is, of 514 00:37:22,350 --> 00:37:23,670 course, to make it simple. 515 00:37:23,670 --> 00:37:25,630 I'd give a name to it, it's just that here it's a 516 00:37:25,630 --> 00:37:28,200 parameterized name. 517 00:37:28,200 --> 00:37:31,460 It's a name that depends upon, explicitly, the lexically 518 00:37:31,460 --> 00:37:34,050 apparent value of n. 519 00:37:37,130 --> 00:37:40,210 So you can think of this as a long name. 520 00:37:40,210 --> 00:37:45,150 And here, I've solved my problem by naming the term 521 00:37:45,150 --> 00:37:49,220 generation procedures within an n in them. 522 00:37:55,080 --> 00:37:57,140 Are there any questions? 523 00:37:57,140 --> 00:37:58,380 Oh, yes, David. 524 00:37:58,380 --> 00:38:04,820 AUDIENCE: Is the only solution to the problem you raise to 525 00:38:04,820 --> 00:38:06,470 create another procedure? 526 00:38:06,470 --> 00:38:09,020 In other words, can this only work in languages that are 527 00:38:09,020 --> 00:38:12,402 capable of defining objects as procedures? 528 00:38:12,402 --> 00:38:13,765 PROFESSOR: Oh, I see. 529 00:38:16,530 --> 00:38:20,530 My solution to making this abstraction, when I didn't 530 00:38:20,530 --> 00:38:23,950 want include the procedure inside the body, depends upon 531 00:38:23,950 --> 00:38:28,190 my ability to return a procedure or export one. 532 00:38:28,190 --> 00:38:30,410 And that's right. 533 00:38:30,410 --> 00:38:33,550 If I don't have that, then I just don't have this ability 534 00:38:33,550 --> 00:38:39,490 to make an abstraction in a way where I don't have 535 00:38:39,490 --> 00:38:40,930 possibilities of symbol conflicts that were 536 00:38:40,930 --> 00:38:43,000 unanticipated. 537 00:38:43,000 --> 00:38:45,610 That's right. 538 00:38:45,610 --> 00:38:52,690 I consider being able to return the procedural value 539 00:38:52,690 --> 00:38:57,780 and, therefore, to sort of have first class procedures, 540 00:38:57,780 --> 00:39:01,840 in general, as being essential to doing very good modular 541 00:39:01,840 --> 00:39:03,700 programming. 542 00:39:03,700 --> 00:39:07,440 Now, indeed there are many other ways to skin this cat. 543 00:39:07,440 --> 00:39:10,500 What you can do is take for each of the bad things that 544 00:39:10,500 --> 00:39:13,420 you have to worry about, you can make a special feature 545 00:39:13,420 --> 00:39:15,840 that covers that thing. 546 00:39:15,840 --> 00:39:17,930 You can make a package system. 547 00:39:17,930 --> 00:39:22,240 You can make a module system as in Ada, et cetera. 548 00:39:22,240 --> 00:39:26,440 And all of those work, or they cover little regions of it. 549 00:39:26,440 --> 00:39:28,820 The thing is that returning procedures as values cover all 550 00:39:28,820 --> 00:39:35,820 of those problems. And so it's the simplest mechanism that 551 00:39:35,820 --> 00:39:40,110 gives you the best modularity, gives you all of the known 552 00:39:40,110 --> 00:39:45,590 modularity mechanisms. 553 00:39:45,590 --> 00:39:48,248 Well, I suppose it's time for the next break, thank you. 554 00:39:48,248 --> 00:40:41,871 [MUSIC PLAYING] 555 00:40:41,871 --> 00:40:43,690 PROFESSOR: Well, yesterday when you learned about 556 00:40:43,690 --> 00:40:52,110 streams, Hal worried to you about the order of evaluation 557 00:40:52,110 --> 00:40:55,420 and delayed arguments to procedures. 558 00:40:55,420 --> 00:41:00,620 The way we played with streams yesterday, it was the 559 00:41:00,620 --> 00:41:07,170 responsibility of the caller and the callee to both agree 560 00:41:07,170 --> 00:41:12,180 that an argument was delayed, and the callee must force the 561 00:41:12,180 --> 00:41:15,250 argument if it needs the answer. 562 00:41:15,250 --> 00:41:18,400 So there had to be a lot of hand shaking between the 563 00:41:18,400 --> 00:41:26,100 designer of a procedure and user of it over delayedness. 564 00:41:26,100 --> 00:41:29,670 That turns out, of course, to be a fairly bad thing, it 565 00:41:29,670 --> 00:41:33,120 works all right with streams. But as a general thing, what 566 00:41:33,120 --> 00:41:37,520 you want is an idea to have a locus, a decision, a design 567 00:41:37,520 --> 00:41:40,580 decision in general, to have a place where it's made, 568 00:41:40,580 --> 00:41:45,900 explicitly, and notated in a clear way. 569 00:41:45,900 --> 00:41:48,780 And so it's not a very good idea to have to have an 570 00:41:48,780 --> 00:41:52,670 agreement, between the person who writes a procedure and the 571 00:41:52,670 --> 00:41:56,730 person who calls it, about such details as, maybe, the 572 00:41:56,730 --> 00:41:59,500 arguments of evaluation, the order of evaluation. 573 00:41:59,500 --> 00:42:00,750 Although, that's not so bad. 574 00:42:00,750 --> 00:42:02,920 I mean, we have other such agreements like, 575 00:42:02,920 --> 00:42:04,540 the input's a number. 576 00:42:04,540 --> 00:42:07,650 But it would be nice if only one of these guys could take 577 00:42:07,650 --> 00:42:11,020 responsibility, completely. 578 00:42:11,020 --> 00:42:15,510 Now this is not a new idea. 579 00:42:15,510 --> 00:42:22,020 ALGOL 60 had two different ways of calling a procedure. 580 00:42:22,020 --> 00:42:25,590 The arguments could be passed by name or by value. 581 00:42:25,590 --> 00:42:31,110 And what that meant was that a name argument was delayed. 582 00:42:31,110 --> 00:42:34,020 That when you passed an argument by name, that its 583 00:42:34,020 --> 00:42:39,620 value would only be obtained if you accessed that argument. 584 00:42:42,290 --> 00:42:45,870 So what I'd like to do now is show you, first of all, a 585 00:42:45,870 --> 00:42:48,040 little bit about, again, we're going to make a modification 586 00:42:48,040 --> 00:42:50,320 to a language. 587 00:42:50,320 --> 00:42:53,370 In this case, we're going to add a feature. 588 00:42:53,370 --> 00:42:56,900 We're going to add the feature of, by name parameters, if you 589 00:42:56,900 --> 00:43:00,430 will, or delayed parameters. 590 00:43:00,430 --> 00:43:05,580 Because, in fact, the default in our Lisp system is by the 591 00:43:05,580 --> 00:43:08,220 value of a pointer. 592 00:43:08,220 --> 00:43:10,530 A pointer is copied, but the data structure it 593 00:43:10,530 --> 00:43:13,410 points at is not. 594 00:43:13,410 --> 00:43:17,580 But I'd like to, in fact, show you is how you add name 595 00:43:17,580 --> 00:43:19,990 arguments as well. 596 00:43:19,990 --> 00:43:23,100 Now again, why would we need such a thing? 597 00:43:23,100 --> 00:43:26,930 Well supposing we wanted to invent certain kinds of what 598 00:43:26,930 --> 00:43:29,720 otherwise would be special forms, reserve words? 599 00:43:29,720 --> 00:43:32,180 But I'd rather not take up reserve words. 600 00:43:32,180 --> 00:43:36,360 I want procedures that can do things like if. 601 00:43:36,360 --> 00:43:39,420 If is special, or cond, or whatever it is. 602 00:43:39,420 --> 00:43:40,600 It's the same thing. 603 00:43:40,600 --> 00:43:43,080 It's special in that it determines whether or not to 604 00:43:43,080 --> 00:43:48,360 evaluate the consequent or the alternative based on the value 605 00:43:48,360 --> 00:43:50,840 of the predicate part of an expression. 606 00:43:50,840 --> 00:43:54,230 So taking the value of one thing determines whether or 607 00:43:54,230 --> 00:43:57,270 not to do something else. 608 00:43:57,270 --> 00:44:00,240 Whereas all the procedures like plus, the ones that we 609 00:44:00,240 --> 00:44:05,900 can define right now, evaluate all of their arguments before 610 00:44:05,900 --> 00:44:08,670 application. 611 00:44:08,670 --> 00:44:11,750 So, for example, supposing I wish to be able to define 612 00:44:11,750 --> 00:44:19,452 something like the reverse of if in terms of if. 613 00:44:19,452 --> 00:44:20,702 Call it unless. 614 00:44:24,890 --> 00:44:26,760 We've a predicate, a consequent, and an 615 00:44:26,760 --> 00:44:28,190 alternative. 616 00:44:28,190 --> 00:44:30,995 Now what I would like to sort of be able to do is say-- oh, 617 00:44:30,995 --> 00:44:32,440 I'll do it in terms of cond. 618 00:44:32,440 --> 00:44:41,660 Cond, if not the predicate, then take the consequent, 619 00:44:41,660 --> 00:44:45,350 otherwise, take the alternative. 620 00:44:51,290 --> 00:44:54,320 Now, what I'd like this to mean, is supposing I do 621 00:44:54,320 --> 00:44:56,920 something like this. 622 00:44:56,920 --> 00:45:05,860 I'd like this unless say if equals one, 0, then the answer 623 00:45:05,860 --> 00:45:11,350 is two, otherwise, the quotient of one and 0. 624 00:45:15,980 --> 00:45:20,170 What I'd like that to mean is the result of substituting 625 00:45:20,170 --> 00:45:23,450 equal one, 0, and two, and the quotient of one, 0 626 00:45:23,450 --> 00:45:25,580 for p, c, and a. 627 00:45:25,580 --> 00:45:28,750 I'd like that to mean, and this is funny, I'd like it to 628 00:45:28,750 --> 00:45:40,940 transform into or mean cond not equal one, 0, then the 629 00:45:40,940 --> 00:45:48,910 result is two, otherwise I want it to be the 630 00:45:48,910 --> 00:45:51,160 quotient one and 0. 631 00:45:54,480 --> 00:45:56,210 Now, you know that if I were to type this into 632 00:45:56,210 --> 00:45:59,970 Lisp, I'd get a two. 633 00:45:59,970 --> 00:46:02,910 There's no problem with that. 634 00:46:02,910 --> 00:46:05,940 However, if I were to type this into Lisp, because all 635 00:46:05,940 --> 00:46:09,590 the arguments are evaluated before I start, then I'm going 636 00:46:09,590 --> 00:46:10,840 to get an error out of this. 637 00:46:13,380 --> 00:46:16,130 So that if the substitutions work at all, of course, I 638 00:46:16,130 --> 00:46:16,880 would get the right answer. 639 00:46:16,880 --> 00:46:20,160 But here's a case where the substitutions don't work. 640 00:46:22,920 --> 00:46:23,860 I don't get the wrong answer. 641 00:46:23,860 --> 00:46:24,670 I get no answer. 642 00:46:24,670 --> 00:46:25,920 I get an error. 643 00:46:28,420 --> 00:46:31,860 Now, however, I'd like to be able to make my definition so 644 00:46:31,860 --> 00:46:34,270 that this kind of thing works. 645 00:46:34,270 --> 00:46:36,010 What I want to do is say something 646 00:46:36,010 --> 00:46:39,930 special about c and a. 647 00:46:39,930 --> 00:46:42,715 I want them to be delayed automatically. 648 00:46:46,300 --> 00:46:51,520 I don't want them to be evaluated at the time I call. 649 00:46:51,520 --> 00:46:52,980 So I'm going to make a declaration, and then I'm 650 00:46:52,980 --> 00:46:55,600 going to see how to implement such a declaration. 651 00:46:55,600 --> 00:46:58,870 But again, I want you to say to yourself, oh, this is an 652 00:46:58,870 --> 00:47:02,140 interesting kluge he's adding in here. 653 00:47:02,140 --> 00:47:05,750 The piles of kluges make a big complicated mess. 654 00:47:05,750 --> 00:47:08,240 And is this going to foul up something 655 00:47:08,240 --> 00:47:10,120 else that might occur. 656 00:47:10,120 --> 00:47:13,860 First of all, is it syntactically unambiguous? 657 00:47:13,860 --> 00:47:16,120 Well, it will be syntactically unambiguous with what we've 658 00:47:16,120 --> 00:47:17,840 seen so far. 659 00:47:17,840 --> 00:47:21,670 But what I'm going to do may, in fact, cause trouble. 660 00:47:21,670 --> 00:47:25,450 It may be that the thing I had will conflict with type 661 00:47:25,450 --> 00:47:28,700 declarations I might want to add in the future for giving 662 00:47:28,700 --> 00:47:31,730 some system, some compiler or something, the ability to 663 00:47:31,730 --> 00:47:34,300 optimize given the types are known. 664 00:47:34,300 --> 00:47:37,130 Or it might conflict with other types of declarations I 665 00:47:37,130 --> 00:47:40,570 might want to make about the formal parameters. 666 00:47:40,570 --> 00:47:44,520 So I'm not making a general mechanism here where I can add 667 00:47:44,520 --> 00:47:44,925 declarations. 668 00:47:44,925 --> 00:47:46,750 And I would like to be able to do that. 669 00:47:46,750 --> 00:47:51,010 But I don't want to talk about that right now. 670 00:47:51,010 --> 00:47:53,680 So here I'm going to do, I'm going to build a kluge. 671 00:47:57,050 --> 00:48:08,770 So we're going to define unless of a predicate-- 672 00:48:08,770 --> 00:48:10,180 and I'm going to call these by name-- 673 00:48:12,810 --> 00:48:14,930 the consequent, and name the alternative. 674 00:48:19,850 --> 00:48:22,670 Huh, huh-- 675 00:48:22,670 --> 00:48:25,280 I got caught in the corner. 676 00:48:31,240 --> 00:48:37,165 If not p then the result is c, else-- 677 00:48:40,110 --> 00:48:41,360 that's what I'd like. 678 00:48:44,670 --> 00:48:49,500 Where I can explicitly declare certain of the parameters to 679 00:48:49,500 --> 00:48:51,650 be delayed, to be computed later. 680 00:48:55,008 --> 00:48:57,910 Now, this is actually a very complicated modification to an 681 00:48:57,910 --> 00:49:00,450 interpreter rather than a simple one. 682 00:49:00,450 --> 00:49:05,270 The ones you saw before, dynamic binding or adding 683 00:49:05,270 --> 00:49:07,630 indefinite argument procedures, 684 00:49:07,630 --> 00:49:09,280 is relatively simple. 685 00:49:09,280 --> 00:49:12,120 But this one changes a basic strategy. 686 00:49:12,120 --> 00:49:18,070 The problem here is that our interpreter, as written, 687 00:49:18,070 --> 00:49:24,420 evaluates a combination by evaluating the procedure, the 688 00:49:24,420 --> 00:49:26,910 operator producing the procedure, and evaluating the 689 00:49:26,910 --> 00:49:31,410 operands producing the arguments, and then doing 690 00:49:31,410 --> 00:49:36,110 apply of the procedure to the arguments. 691 00:49:36,110 --> 00:49:40,540 However, here, I don't want to evaluate the operands to 692 00:49:40,540 --> 00:49:44,640 produce the arguments until after I examined the procedure 693 00:49:44,640 --> 00:49:46,810 to see what the procedure's declarations look like. 694 00:49:49,590 --> 00:49:52,680 So let's look at that. 695 00:49:52,680 --> 00:49:57,480 Here we have a changed evaluator. 696 00:49:57,480 --> 00:50:02,110 I'm starting with the simple lexical evaluator, not 697 00:50:02,110 --> 00:50:06,730 dynamic, but we're going to have to do something sort of 698 00:50:06,730 --> 00:50:09,750 similar in some ways. 699 00:50:09,750 --> 00:50:13,710 Because of the fact that, if I delay a procedure-- 700 00:50:13,710 --> 00:50:15,790 I'm sorry-- delay an argument to a procedure, I'm going to 701 00:50:15,790 --> 00:50:19,360 have to attach and environment to it. 702 00:50:19,360 --> 00:50:23,380 Remember how Hal implemented delay. 703 00:50:23,380 --> 00:50:28,650 Hal implemented delay as being a procedure of no arguments 704 00:50:28,650 --> 00:50:31,180 which does some expression. 705 00:50:31,180 --> 00:50:32,670 That's what delay of the expression is. 706 00:50:35,370 --> 00:50:36,620 --of that expression. 707 00:50:39,180 --> 00:50:40,950 This turned into something like this. 708 00:50:44,520 --> 00:50:47,760 Now, however, if I evaluate a lambda expression, I have to 709 00:50:47,760 --> 00:50:49,010 capture the environment. 710 00:50:51,410 --> 00:50:56,920 The reason why is because there are variables in there 711 00:50:56,920 --> 00:51:00,280 who's meaning I wish to derive from the context where this 712 00:51:00,280 --> 00:51:01,530 was written. 713 00:51:04,010 --> 00:51:06,095 So that's why a lambda does the job. 714 00:51:06,095 --> 00:51:08,070 It's the right thing. 715 00:51:08,070 --> 00:51:17,070 And such that the forcing of a delayed expression was same 716 00:51:17,070 --> 00:51:21,090 thing as calling that with no arguments. 717 00:51:21,090 --> 00:51:24,100 It's just the opposite of this. 718 00:51:24,100 --> 00:51:28,120 Producing an environment of the call which is, in fact, 719 00:51:28,120 --> 00:51:31,713 the environment where this was defined with an extra frame in 720 00:51:31,713 --> 00:51:33,132 it that's empty. 721 00:51:33,132 --> 00:51:36,240 I don't care about that. 722 00:51:36,240 --> 00:51:42,460 Well, if we go back to this slide, since it's the case, if 723 00:51:42,460 --> 00:51:45,290 we look at this for a second, everything is the same as it 724 00:51:45,290 --> 00:51:51,980 was before except the case of applications or combinations. 725 00:51:51,980 --> 00:51:54,680 And combinations are going to do two things. 726 00:51:54,680 --> 00:51:58,010 One, is I have to evaluate the procedure-- 727 00:51:58,010 --> 00:52:00,425 forget the procedure-- by evaluating the operator. 728 00:52:00,425 --> 00:52:02,380 That's what you see right here. 729 00:52:02,380 --> 00:52:04,990 I have to make sure that that's current, that is not a 730 00:52:04,990 --> 00:52:08,530 delayed object, and evaluate that to the point where it's 731 00:52:08,530 --> 00:52:10,730 forced now. 732 00:52:10,730 --> 00:52:18,460 And then I have to somehow apply that to the operands. 733 00:52:18,460 --> 00:52:20,040 But I have to keep the environment, pass that 734 00:52:20,040 --> 00:52:21,530 environmental along. 735 00:52:21,530 --> 00:52:23,710 So some of those operands I may have to delay. 736 00:52:23,710 --> 00:52:29,302 I may have to attach that environment to those operands. 737 00:52:29,302 --> 00:52:32,990 This is a rather complicated thing happening here. 738 00:52:32,990 --> 00:52:34,240 Looking at that in apply. 739 00:52:36,400 --> 00:52:39,370 Apply, well it has a primitive procedure 740 00:52:39,370 --> 00:52:42,610 thing just like before. 741 00:52:42,610 --> 00:52:44,390 But the compound one is a little more interesting. 742 00:52:47,250 --> 00:52:50,920 I have to evaluate the body, just as before, in an 743 00:52:50,920 --> 00:52:56,010 environment which is the result of binding some formal 744 00:52:56,010 --> 00:53:00,290 parameters to arguments in the environment. 745 00:53:00,290 --> 00:53:01,530 That's true. 746 00:53:01,530 --> 00:53:03,070 The environment is the one that comes from 747 00:53:03,070 --> 00:53:03,820 the procedure now. 748 00:53:03,820 --> 00:53:08,040 It's a lexical language, statically bound. 749 00:53:08,040 --> 00:53:11,230 However, one thing I have to do is strip off the 750 00:53:11,230 --> 00:53:12,960 declarations to get the names of the variables. 751 00:53:12,960 --> 00:53:15,450 That's what this guy does, vnames. 752 00:53:15,450 --> 00:53:17,940 And the other thing I have to do is process these 753 00:53:17,940 --> 00:53:21,770 declarations, deciding which of these operands-- 754 00:53:21,770 --> 00:53:24,150 that's the operands now, as opposed to the arguments-- 755 00:53:24,150 --> 00:53:28,010 which of these operands to evaluate, and which of them 756 00:53:28,010 --> 00:53:33,770 are to be encapsulated in delays of some sort. 757 00:53:37,280 --> 00:53:40,720 The other thing you see here is that we got a primitive, a 758 00:53:40,720 --> 00:53:43,170 primitive like plus, had better 759 00:53:43,170 --> 00:53:45,820 get at the real operands. 760 00:53:45,820 --> 00:53:47,690 So here is a place where we're going to have to force them. 761 00:53:47,690 --> 00:53:49,306 And we're going to look at what evlist is going to have 762 00:53:49,306 --> 00:53:51,340 to do a bunch of forces. 763 00:53:51,340 --> 00:53:52,780 So we have two different kinds of evlist now. 764 00:53:52,780 --> 00:53:55,980 We have evlist and gevlist. Gevlist is going to wrap 765 00:53:55,980 --> 00:53:59,870 delays around some things and force others, evaluate others. 766 00:53:59,870 --> 00:54:07,900 And this guy's going to do some forcing of things. 767 00:54:07,900 --> 00:54:10,770 Just looking at this a little bit, this is a game you must 768 00:54:10,770 --> 00:54:12,250 play for yourself, you know. 769 00:54:12,250 --> 00:54:14,870 It's not something that you're going to see all possible 770 00:54:14,870 --> 00:54:19,730 variations on an evaluator talking to me. 771 00:54:19,730 --> 00:54:21,410 What you have to do is do this for yourself. 772 00:54:21,410 --> 00:54:24,610 And after you feel this, you play this a bit, you get to 773 00:54:24,610 --> 00:54:26,580 see all the possible design decisions and what they might 774 00:54:26,580 --> 00:54:29,930 mean, and how they interact with each other. 775 00:54:29,930 --> 00:54:33,160 So what languages might have in them. 776 00:54:33,160 --> 00:54:35,340 And what are some of the consistent sets that make a 777 00:54:35,340 --> 00:54:37,200 legitimate language. 778 00:54:37,200 --> 00:54:39,135 Whereas what things are complicated kluges that are 779 00:54:39,135 --> 00:54:41,850 just piles of junk. 780 00:54:41,850 --> 00:54:45,050 So evlist of course, over here, just as I said, is a 781 00:54:45,050 --> 00:54:49,450 list of operands which are going to be undelayed after 782 00:54:49,450 --> 00:54:50,750 evaluation. 783 00:54:50,750 --> 00:54:53,600 So these are going to be forced, whatever 784 00:54:53,600 --> 00:54:56,050 that's going to mean. 785 00:54:56,050 --> 00:54:58,490 And gevlist, which is the next thing-- 786 00:55:01,320 --> 00:55:04,040 Thank you. 787 00:55:04,040 --> 00:55:09,810 What we see here, well there's a couple of possibilities. 788 00:55:09,810 --> 00:55:13,750 Either it's a normal, ordinary thing, a symbol sitting there 789 00:55:13,750 --> 00:55:18,020 like the predicate in the unless, and that's 790 00:55:18,020 --> 00:55:19,390 what we have here. 791 00:55:19,390 --> 00:55:21,710 In which case, this is intended to be evaluated in 792 00:55:21,710 --> 00:55:23,340 applicative order. 793 00:55:23,340 --> 00:55:25,630 And it's, essentially, just what we had before. 794 00:55:25,630 --> 00:55:30,400 It's mapping eval down the list. In other words, I 795 00:55:30,400 --> 00:55:35,690 evaluate the first expression and continue gevlisting the 796 00:55:35,690 --> 00:55:37,900 CDR of the expression in the environment. 797 00:55:37,900 --> 00:55:43,600 However, it's possible that this is a name parameter. 798 00:55:43,600 --> 00:55:47,320 If it's a name parameter, I want to put a delay in which 799 00:55:47,320 --> 00:55:53,480 combines that expression, which I'm calling by name, 800 00:55:53,480 --> 00:55:59,250 with the environment that's available at this time and 801 00:55:59,250 --> 00:56:02,790 passing that as the parameter. 802 00:56:02,790 --> 00:56:04,350 And this is part of the mapping process 803 00:56:04,350 --> 00:56:05,600 that you see here. 804 00:56:09,070 --> 00:56:12,040 The only other interesting place in this 805 00:56:12,040 --> 00:56:14,700 interpreter is cond. 806 00:56:14,700 --> 00:56:16,440 People tend to write this thing, and then they leave 807 00:56:16,440 --> 00:56:18,550 this one out. 808 00:56:18,550 --> 00:56:20,510 There's a place where you have to force. 809 00:56:20,510 --> 00:56:25,260 Conditionals have to know whether or not the answer is 810 00:56:25,260 --> 00:56:25,990 true or false. 811 00:56:25,990 --> 00:56:28,550 It's like a primitive. 812 00:56:28,550 --> 00:56:31,890 When you do a conditional, you have to force. 813 00:56:31,890 --> 00:56:32,880 Now, I'm not going to look at any more 814 00:56:32,880 --> 00:56:34,350 of this in any detail. 815 00:56:34,350 --> 00:56:36,750 It isn't very exciting. 816 00:56:36,750 --> 00:56:38,990 And what's left is how you make delays. 817 00:56:38,990 --> 00:56:42,680 Well, delays are data structures which contain an 818 00:56:42,680 --> 00:56:44,840 expression, an environment, and a type on them. 819 00:56:44,840 --> 00:56:46,680 And it says they're a thunk. 820 00:56:46,680 --> 00:56:50,100 That comes from ALGOL language, and it's claimed to 821 00:56:50,100 --> 00:56:52,970 be the sound of something being pushed on a stack. 822 00:56:52,970 --> 00:56:53,410 I don't know. 823 00:56:53,410 --> 00:56:57,830 I was not an ALGOLician or an ALGOLite or whatever, so I 824 00:56:57,830 --> 00:56:58,740 don't know. 825 00:56:58,740 --> 00:57:00,270 But that's what was claimed. 826 00:57:00,270 --> 00:57:03,400 And undelay is something which will recursively undelay 827 00:57:03,400 --> 00:57:07,860 thunks until the thunk becomes something which isn't a thunk. 828 00:57:07,860 --> 00:57:09,930 This is the way you implement a call by name 829 00:57:09,930 --> 00:57:12,050 like thing in ALGOL. 830 00:57:12,050 --> 00:57:15,210 And that's about all there is. 831 00:57:15,210 --> 00:57:16,460 Are there any questions? 832 00:57:26,840 --> 00:57:27,560 AUDIENCE: Gerry? 833 00:57:27,560 --> 00:57:29,626 PROFESSOR: Yes, Vesko? 834 00:57:29,626 --> 00:57:33,900 AUDIENCE: I noticed you avoided calling by name in the 835 00:57:33,900 --> 00:57:38,480 primitive procedures, I was wondering what 836 00:57:38,480 --> 00:57:39,350 cause you have on that? 837 00:57:39,350 --> 00:57:40,070 You never need that? 838 00:57:40,070 --> 00:57:44,720 PROFESSOR: Vesko is asking if it's ever reasonable to call a 839 00:57:44,720 --> 00:57:47,140 primitive procedure by name? 840 00:57:47,140 --> 00:57:49,270 The answer is, yes. 841 00:57:49,270 --> 00:57:51,680 There's one particular case where it's reasonable, 842 00:57:51,680 --> 00:57:52,930 actually two. 843 00:57:56,050 --> 00:57:59,250 Construction of a data structure like cons where 844 00:57:59,250 --> 00:58:01,100 making an array if you have arrays with 845 00:58:01,100 --> 00:58:03,690 any number of elements. 846 00:58:03,690 --> 00:58:07,440 It's unnecessary to evaluate those arguments. 847 00:58:07,440 --> 00:58:10,180 All you need is promises to evaluate those arguments if 848 00:58:10,180 --> 00:58:11,160 you look at them. 849 00:58:11,160 --> 00:58:17,310 If I cons together two things, then I could cons together the 850 00:58:17,310 --> 00:58:21,830 promises just as easily as I can cons together the things. 851 00:58:21,830 --> 00:58:23,720 And it's not even when I CAR CDR them that I 852 00:58:23,720 --> 00:58:24,840 have to look at them. 853 00:58:24,840 --> 00:58:26,150 That just gets out the promises and 854 00:58:26,150 --> 00:58:28,260 passes them to somebody. 855 00:58:28,260 --> 00:58:31,320 That's why the lambda calculus definition, the Alonzo Church 856 00:58:31,320 --> 00:58:34,420 definition of CAR, CDR, and cons makes sense. 857 00:58:34,420 --> 00:58:36,630 It's because no work is done in CAR, CDR, and cons, it's 858 00:58:36,630 --> 00:58:40,760 just shuffling data, it's just routing, if you will. 859 00:58:40,760 --> 00:58:42,960 However, the things that do have to look at data are 860 00:58:42,960 --> 00:58:45,280 things like plus. 861 00:58:45,280 --> 00:58:47,910 Because they have a look at the bits that the numbers are 862 00:58:47,910 --> 00:58:50,220 made out of, unless they're lambda calculus 863 00:58:50,220 --> 00:58:52,460 numbers which are funny. 864 00:58:52,460 --> 00:58:54,630 They have to look at the bits to be able to crunch them 865 00:58:54,630 --> 00:58:55,880 together to do the add. 866 00:58:59,210 --> 00:59:03,280 So, in fact, data constructors, data selectors, 867 00:59:03,280 --> 00:59:08,500 and, in fact, things that side-effect data objects don't 868 00:59:08,500 --> 00:59:13,300 need to do any forcing in the laziest possible interpreters. 869 00:59:16,460 --> 00:59:18,700 On the other hand predicates on data structures have to. 870 00:59:21,710 --> 00:59:23,560 Is this a pair? 871 00:59:23,560 --> 00:59:24,640 Or is it a symbol? 872 00:59:24,640 --> 00:59:25,690 Well, you better find out. 873 00:59:25,690 --> 00:59:26,940 You got to look at it then. 874 00:59:30,300 --> 00:59:31,550 Any other questions? 875 00:59:40,050 --> 00:59:41,610 Oh, well, I suppose it's time for a break. 876 00:59:41,610 --> 00:59:42,106 Thank you. 877 00:59:42,106 --> 01:00:02,950 [MUSIC PLAYING] 878 01:00:02,950 --> 01:00:04,200 and